//-------------------------------------------------------------------------
/**
   File:   Process.h

   Descr.: Class for starting processes.

   Author: Stefan Leihkauf
   Date:   17.08.2011
*/
//-------------------------------------------------------------------------
#ifndef _PROCESS_H
#define _PROCESS_H
#include "common/types/typedef.h"
#include "process/EnvironmentBlock.h"
#include "process/details/process_io_handles.h"
#include "process/details/process_information.h"

namespace cb { namespace process {

class Process : boost::noncopyable /* not yet copyable */
{
	enum { MaxCommandLine = 32768 };

public:
	/* process priority classes */
	enum Priority {
		AboveNormal = ABOVE_NORMAL_PRIORITY_CLASS,
		BelowNormal = BELOW_NORMAL_PRIORITY_CLASS,
		High 		= HIGH_PRIORITY_CLASS,
		Idle 		= IDLE_PRIORITY_CLASS,
		Normal 		= NORMAL_PRIORITY_CLASS,
		Realtime 	= REALTIME_PRIORITY_CLASS
	};

	/* a set of values used to start a process */
	struct StartupInfo {
		StartupInfo();

		StdString ApplicationName;
		StdString CommandLine;
		StdString WorkingDirectory;

		EnvironmentBlock EnvironmentBlock;

		bool RedirectStandardError;
		bool RedirectStandardInput;
		bool RedirectStandardOutput;
	};

public:
	// construction/destruction
	Process();
	~Process();

	// start process
	bool Start();
	bool Start(const Process::StartupInfo& startupInfo);
	bool Start(const StdString& filename);
	bool Start(const StdString& filename, const StdString& arguments);

	// get process information
	Process::StartupInfo& GetStartupInfo();

private:
	bool StartProcess();

	// build environment block for the process to start
	typedef boost::shared_array<char> PtrByteBuffer;
	PtrByteBuffer buildEnvironmentBlock(const EnvironmentBlock& envBlock);

	// build commandline for the process to start
	typedef boost::shared_array<TCHAR> PtrTCharBuffer;
	PtrTCharBuffer buildCommandLine(const StdString& cmdLine);

	// build applicationname
	StdString buildApplicationName(const StdString& appName);

	// check if process to start is a batch script
	bool isBatchScript(const StdString& appName) const;

private:
	StartupInfo _startupInfo;
	Priority _processPriority;

	typedef detail::process_information ProcessInformation;
	ProcessInformation _processInformation;

	typedef detail::process_io_handles ProcessIOHandles;
	ProcessIOHandles _stdIOHandles;
};

}} // namespace cb::process
#endif //!defined _PROCESS_H